package cn.tedu.charging.order.points;

import com.alibaba.fastjson2.JSON;
import jakarta.websocket.*;
import jakarta.websocket.server.PathParam;
import jakarta.websocket.server.ServerEndpoint;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Component
@Slf4j
@ServerEndpoint("/ws/server/{userId}")
public class WsServerPoint {
    /**
     * 给某个用户发送消息数据 Integer userId,String msg
     */
    public void sendMsg2User(Integer userId,Object msg){
        //1.利用userId获取session对象
        Session session = SESSIONS.get(userId);
        //判断当前这个用户userId是否在线
        if (session!=null) {
            //2.在线就利用session对象推送消息
            try{
                session.getBasicRemote().sendText(JSON.toJSONString(msg));
            }catch (Exception e){
                log.error("发送消息失败",e);
                throw new RuntimeException(e);
            }
        }else{
            log.info("用户{}不在线",userId);
        }

    }
    private static final Map<Integer,Session> SESSIONS=new ConcurrentHashMap<>();
    /**
     * 每当有一个客户端,通过localhost:10090/ws/001建立和我们这个终端serverpoint联系
     * 之后,立刻调用一个方法
     */
    @OnOpen
    public void open(Session session, @PathParam("userId")Integer userId){
        //session表示有个一个客户端成功建立连接
        log.info("客户端成功建立了连接,连接会话是session,sessionId:{},入参userId:{}",session.getId(),userId);
        //利用session对象将欢迎光临的内容推送给客户端
        String msg="欢迎光临";
        try {
            session.getBasicRemote().sendText(msg);
        } catch (IOException e) {
            log.error("发送消息失败",e);
            throw new RuntimeException(e);
        }
        //将建立好的session连接,与客户端传递过来的业务数据userId 在map中做映射存储
        SESSIONS.put(userId,session);
        log.info("当前系统在线人数:{}",SESSIONS.size());
    }
    /**
     * 当客户端建立连接之后,主动断开
     * 立刻调用一个方法
     */
    @OnClose
    public void close(Session session,@PathParam("userId")Integer userId){
        log.info("客户端主动断开了连接,断开的连接session的sessionId:{},入参userId:{}",session.getId(),userId);
        //断开连接 session失效了,应该从map里将其移除
        SESSIONS.remove(userId);
        log.info("当前系统在线人数:{}",SESSIONS.size());
    }
    /**
     * 当客户端建立的连接,出现的通信,或者稳定性导致的异常
     */
    @OnError
    public void error(Throwable e,Session session,@PathParam("userId")Integer userId){
        SESSIONS.remove(userId);
        log.error("客户端连接有异常",e);
    }
    /**
     * 当客户端建立连接之后,一旦客户端向服务端发送信息
     * 服务端调用这个方法处理这个信息的收集
     */
    @OnMessage
    public void messageArrived(String message,Session session,@PathParam("userId")Integer userId){
        log.info("收到客户端发来的消息:{},客户端连接session的id:{},入参userId:{}",message,session.getId(),userId);
        //判断当前客户端到底是谁 将不存在的客户端关闭
        Session currentSession = SESSIONS.get(userId);
        if (!currentSession.getId().equals(session.getId())){
            try {
                //如果我们在记录中存储的session对象和 客户端心跳的session不一样,这个心跳的客户端通知异常断开
                session.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

